package com.byd.base;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.WindowManager;
import com.byd.utils.Lg;

public abstract class BaseActivity extends Activity implements IPresenter, IUIEvent {
	private BasePresenter<? extends BaseActivity> mPresenter;
	private int mLifecycle = Lifecycle.UNKNOWN;
	private long mActiveTime;
	private boolean mAcceptUIEvent;
	private boolean mReallyHidden;
	private boolean mSaveInstanceState = false;
	private boolean mGcWhenDestroy = false;
	private ArrayList<WeakReference<IUserAction>> mUserAction;
	private ArrayList<WeakReference<IUIEvent>> mUIEvent;
	private final Handler mHandler = new Handler(Looper.getMainLooper());
	
	public static class Lifecycle {
		public static final int UNKNOWN = -1;
		public static final int CREATED = 0;
		public static final int STARTED = 1;
		public static final int RESUMED = 2;
		public static final int PAUSED = 3;
		public static final int STOPPED = 4;
		public static final int DESTROYED = 5;
	}

	public BaseActivity() {
		super();
		v("new instance");
	}

	private final String getTagStr() {
		return Lg.BASE_TAG + getClass().getSimpleName();
	}

	protected final void v(Object msg) {
		Lg.v(getTagStr(), msg);
	}

	protected final void d(Object msg) {
		Lg.d(getTagStr(), msg);
	}

	protected final void i(Object msg) {
		Lg.i(getTagStr(), msg);
	}

	protected final void w(Object msg) {
		Lg.w(getTagStr(), msg);
	}

	protected final void e(Object msg) {
		Lg.e(getTagStr(), msg);
	}

	protected final void wtf(Object msg) {
		Lg.wtf(getTagStr(), msg);
	}

	/** 杩斿洖甯冨眬鏂囦欢ID */
	protected abstract int onInflateView();

	/** 鍒涘缓Presenter */
	protected abstract BasePresenter<? extends BaseActivity> onCreatePresenter();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
		mLifecycle = Lifecycle.CREATED;
		setContentView(onInflateView());
		mUserAction = new ArrayList<WeakReference<IUserAction>>();
		mUIEvent = new ArrayList<WeakReference<IUIEvent>>();
		mPresenter = onCreatePresenter();
		onCreate();
		if(mPresenter != null) {
			mPresenter.performCreate(this, this);
		}
	}

	protected abstract void onCreate();

	@Override
	protected void onStart() {
		super.onStart();
		mLifecycle = Lifecycle.STARTED;
		mReallyHidden = false;
		if(mPresenter != null) {
			mPresenter.performStart();
			mPresenter.performActive();
		}
	}

	@Override
	protected void onResume() {
		super.onResume();
		mLifecycle = Lifecycle.RESUMED;
		mActiveTime = System.currentTimeMillis();
		if(mPresenter != null) {
			mPresenter.performResume();
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
		mLifecycle = Lifecycle.PAUSED;
		if(mPresenter != null) {
			mPresenter.performPause();
		}
	}

	@Override
	protected void onStop() {
		super.onStop();
		mLifecycle = Lifecycle.STOPPED;
		mReallyHidden = true;
		if(mPresenter != null) {
			mPresenter.performStop();
			mPresenter.performInactive();
		}
	}

	@Override
	protected final void onDestroy() {
		v("onDestroy");
		super.onDestroy();
		mLifecycle = Lifecycle.DESTROYED;
		onRelease();
		if(mPresenter != null) {
			mPresenter.performDestroy();
		}
		mPresenter = null;
		mUserAction.clear();
		mUserAction = null;
		mUIEvent.clear();
		mUIEvent = null;
		mHandler.removeCallbacksAndMessages(null);
	}
	
	/**鏇夸唬鍘焮@link #onDestroy}*/
	protected void onRelease() {
		//for Override
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		if(mSaveInstanceState) {
			super.onSaveInstanceState(outState);
		}
	}

	protected final void setSaveInstanceState(boolean save) {
		mSaveInstanceState = save;
	}

	@Override
	protected void finalize() throws Throwable {
		i("finalize: " + toString());
		super.finalize();
	}

	protected synchronized final void addFragment(int resId, Class<? extends BaseFragment> cls) {
		try {
			final BaseFragment fragment = cls.newInstance();
			addFragment(resId, fragment);
		}
		catch (final Exception e) {
			Lg.printStackTrace(e);
		}
	}

	protected synchronized final void addFragment(int resId, BaseFragment fragment) {
		final FragmentManager manager = getFragmentManager();
		final FragmentTransaction transaction = manager.beginTransaction();
		transaction.add(resId, fragment, fragment.getClass().getSimpleName());
		transaction.commit();
	}

	protected synchronized final void removeFragment(BaseFragment fragment) {
		final FragmentManager manager = getFragmentManager();
		final FragmentTransaction transaction = manager.beginTransaction();
		transaction.remove(fragment);
		transaction.commit();
	}
	
	/**璁剧疆褰撴Activity閿�姣佸悗锛屾槸鍚﹁皟鐢▄@link System#gc()}*/
	public void setGcWhenDestroy(boolean gc) {
		mGcWhenDestroy = gc;
	}
	
	public boolean isGcWhenDestroy() {
		return mGcWhenDestroy;
	}

	final synchronized void regiesterUIEvent(IUIEvent receiver) {
		final int count = mUIEvent.size();
		WeakReference<IUIEvent> weakEvent;
		IUIEvent uiEvent;
		boolean regiested = false;
		for (int i = count - 1; i >= 0; i--) {
			weakEvent = mUIEvent.get(i);
			if((uiEvent = weakEvent.get()) != null && (regiested = uiEvent.equals(receiver))) {
				break;
			}
			else if(uiEvent == null) {
				mUIEvent.remove(weakEvent);
			}
		}
		if(!regiested) {
			mUIEvent.add(new WeakReference<IUIEvent>(receiver));
		}
	}

	final synchronized void unregiesterUIEvent(IUIEvent receiver) {
		final int count = mUIEvent.size();
		WeakReference<IUIEvent> weakEvent;
		IUIEvent uiEvent;
		for (int i = count - 1; i >= 0; i--) {
			weakEvent = mUIEvent.get(i);
			if((uiEvent = weakEvent.get()) != null && uiEvent.equals(receiver)) {
				mUIEvent.remove(weakEvent);
				break;
			}
			else if(uiEvent == null) {
				mUIEvent.remove(weakEvent);
			}
		}
	}

	final synchronized void sendUIEvent(IUIEvent sender, UIEvent event, Class<?>... filter) {
		final int count = mUIEvent.size();
		WeakReference<IUIEvent> weakEvent;
		IUIEvent receiver;
		for (int i = count - 1; i >= 0; i--) {
			weakEvent = mUIEvent.get(i);
			if((receiver = weakEvent.get()) != null && !receiver.equals(sender) && receiver.isAcceptUIEvent()
					&& isAccept(receiver, filter)) {
				receiver.onRecieveUIEvent(event);
			}
			else if(receiver == null) {
				mUIEvent.remove(weakEvent);
			}
		}
	}

	/**娉ㄥ唽鎺ユ敹{@link UIEvent}*/
	protected final void regiestUIEvent() {
		if(!mAcceptUIEvent) {
			mAcceptUIEvent = true;
			regiesterUIEvent(this);
		}
	}

	/**鍙嶆敞鍐寋@link UIEvent}*/
	protected final void unregiestUIEvent() {
		if(mAcceptUIEvent) {
			mAcceptUIEvent = false;
			unregiesterUIEvent(this);
		}
	}

	@Override
	public void onRecieveUIEvent(UIEvent event) {
		if(mPresenter != null) {
			mPresenter.performUIEvent(event);
		}
	}

	@Override
	public final boolean isAcceptUIEvent() {
		return !mReallyHidden;
	}

	final synchronized void regiesterUserAction(IUserAction receiver) {
		final int count = mUserAction.size();
		WeakReference<IUserAction> weakAction;
		IUserAction userAction;
		for (int i = count - 1; i >= 0; i--) {
			weakAction = mUserAction.get(i);
			// 涔嬫墍浠ラ渶瑕佸垹闄わ紝鏄洜涓烘渶鍚庢敞鍐岀殑蹇呴』鏀惧湪鏈�鍚庯紝鐢ㄤ簬鎷︽埅娑堟伅
			if((userAction = weakAction.get()) != null && userAction.equals(receiver) || userAction == null) {
				mUserAction.remove(weakAction);
			}
		}
		mUserAction.add(new WeakReference<IUserAction>(receiver));
	}

	final synchronized void unregiesterUserAction(IUserAction action) {
		final int count = mUserAction.size();
		WeakReference<IUserAction> weakAction;
		IUserAction receiver;
		for (int i = count - 1; i >= 0; i--) {
			weakAction = mUserAction.get(i);
			if((receiver = weakAction.get()) != null && receiver.equals(action)) {
				mUserAction.remove(weakAction);
				break;
			}
			else if(receiver == null) {
				mUserAction.remove(weakAction);
			}
		}
	}

	@Override
	public synchronized void onBackPressed() {
		boolean expense = false;
		final int count = mUserAction.size();
		WeakReference<IUserAction> weakAction;
		IUserAction receiver;
		for (int i = count - 1; i >= 0; i--) {
			weakAction = mUserAction.get(i);
			if((receiver = weakAction.get()) != null && receiver.isAcceptUserAction()
					&& (expense = receiver.onBackPressed())) {
				break;
			}
			else if(receiver == null) {
				mUserAction.remove(weakAction);
			}
		}
		if(!expense) {
			super.onBackPressed();
		}
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		if(ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
			if(onWindowTouchDown(ev)) {
				return true;
			}
		}
		return super.dispatchTouchEvent(ev);
	}

	/** 鐢ㄦ埛鎸変笅瑙︽懜灞�
	 * 
	 * @return 杩斿洖true鍒欒〃绀烘嫤鎴鍔ㄤ綔锛涜繑鍥瀎alse鍒欒〃绀轰笉鎷︽埅 */
	protected synchronized boolean onWindowTouchDown(MotionEvent ev) {
		boolean expense = false;
		final int count = mUserAction.size();
		WeakReference<IUserAction> weakAction;
		IUserAction receiver;
		for (int i = count - 1; i >= 0; i--) {
			weakAction = mUserAction.get(i);
			if((receiver = weakAction.get()) != null && receiver.isAcceptUserAction()
					&& (expense = receiver.onWindowTouchDown(ev))) {
				break;
			}
			else if(receiver == null) {
				mUserAction.remove(weakAction);
			}
		}
		return expense;
	}

	@Override
	public final void sendUIEvent(UIEvent event, Class<?>... filter) {
		sendUIEvent(this, event, filter);
	}

	private final boolean isAccept(Object receiver, Class<?>... filter) {
		if(receiver == null) {
			return false;
		}
		else if(filter == null || filter.length == 0) {
			return true;
		}
		final String clsName = receiver.getClass().getName();
		for (final Class<?> cls : filter) {
			if(cls != null && clsName.equals(cls.getName())) {
				return true;
			}
		}
		return false;
	}
	
	public int getLifecycle() {
		return mLifecycle;
	}
	
	public long getActiveTime() {
		return mActiveTime;
	}

	protected final int getColor(int id) {
		return getResources().getColor(id);
	}
	
	public boolean getBoolean(int id) {
		return getResources().getBoolean(id);
	}

	protected final float getDimension(int id) {
		return getResources().getDimension(id);
	}

	protected final int getDimensionPixelOffset(int id) {
		return getResources().getDimensionPixelOffset(id);
	}

	protected final int getDimensionPixelSize(int id) {
		return getResources().getDimensionPixelSize(id);
	}

	protected final String[] getStringArray(int id) {
		return getResources().getStringArray(id);
	}

	protected final int getInteger(int id) {
		return getResources().getInteger(id);
	}

	protected final int[] getIntArray(int id) {
		return getResources().getIntArray(id);
	}

	protected final DisplayMetrics getDisplayMetrics() {
		return getResources().getDisplayMetrics();
	}

	protected final Configuration getConfiguration() {
		return getResources().getConfiguration();
	}

	protected final boolean post(Runnable r) {
		return mHandler.post(r);
	}

	protected final boolean postSingle(Runnable r) {
		mHandler.removeCallbacks(r);
		return mHandler.post(r);
	}

	protected final boolean postDelayed(Runnable r, long delayMillis) {
		return mHandler.postDelayed(r, delayMillis);
	}

	protected final boolean postSingleDelayed(Runnable r, long delayMillis) {
		mHandler.removeCallbacks(r);
		return mHandler.postDelayed(r, delayMillis);
	}

	protected final void removeCallbacks(Runnable r) {
		mHandler.removeCallbacks(r);
	}
}
